/* Copyright © Worklight Ltd. 2006-2011.  All rights reserved. */

package com.worklight.androidgap.push;

import java.io.IOException;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import com.google.android.c2dm.C2DMBaseReceiver;
import com.worklight.androidgap.WLAndroidUtils;
import com.worklight.androidgap.WLDroidGap;

public class C2DMReceiver extends C2DMBaseReceiver {
	
	// Resources
	public final static int RES_PUSH_NOTIFICATION_ICON = com.PersonalDevelopmentApp.R.drawable.push;
	public final static int RES_PUSH_NOIIFICATION_TITLE = com.PersonalDevelopmentApp.R.string.push_notification_title;
	
	//Intet ids - should be unique to the app
	private static final String APP_NAME = "com.PersonalDevelopmentApp.PersonalDevelopmentApp";
	public static final String SHORT_APP_NAME = "PersonalDevelopmentApp";
	
	public static final String C2DM_NOTIFICATION = APP_NAME + ".NOTIFICATION";
	public static final String C2DM_REGISTERED = APP_NAME + ".C2DM_REGISTERED";
	public static final String C2DM_UNREGISTERED = APP_NAME + ".C2DM_UNREGISTERED";
	public static final String C2DM_MESSAGE = APP_NAME + ".C2DM_MESSAGE";
	public static final String C2DM_ERROR = APP_NAME + ".C2DM_ERROR";

	public static final String C2DM_EXTRA_ALERT = "alert";
	public static final String C2DM_EXTRA_BADGE = "badge";
	public static final String C2DM_EXTRA_SOUND = "sound";
	public static final String C2DM_EXTRA_PAYLOAD = "payload";
	
	public static final String C2DM_EXTRA_MESSAGE = "message";
	public static final String C2DM_EXTRA_REGISTRATION_ID = "registrationId";
	public static final String C2DM_EXTRA_ERROR_ID = "errorId";

	public C2DMReceiver() {
		super(WLDroidGap.getWLConfig() != null ? WLDroidGap.getWLConfig().getC2DMSender() : "");
	}
	
	@Override
	public void onRegistered(Context context, String registrationId) throws IOException {
		WLAndroidUtils.debug("Registered at the C2DM server with registration id " + registrationId);
		Intent intent = new Intent(C2DM_REGISTERED);
		intent.putExtra(C2DM_EXTRA_REGISTRATION_ID, registrationId);
		context.sendBroadcast(intent);
	}

	@Override
	public void onUnregistered(Context context) {
		WLAndroidUtils.debug("Unregistered at the C2DM server");
		context.sendBroadcast(new Intent(C2DM_UNREGISTERED));
	}

	@Override
	protected void onMessage(Context context, Intent intent) {
		WLAndroidUtils.debug("Received a message from the C2DM server");
		Message message = new Message();
		Bundle info = intent.getExtras();
		message.alert = info.getString(C2DM_EXTRA_ALERT);
		try {
			message.badge = Integer.parseInt(info.getString(C2DM_EXTRA_BADGE), 10);
		} catch (Exception e) {
			WLAndroidUtils.warning("Problem to parse " + info.getString(C2DM_EXTRA_BADGE) + " badge into Integer.");
		}
		message.sound = info.getString(C2DM_EXTRA_SOUND);
		message.payload = info.getString(C2DM_EXTRA_PAYLOAD);

		intent = new Intent(C2DM_MESSAGE);
		intent.putExtra(C2DM_EXTRA_MESSAGE, message);
		context.sendOrderedBroadcast(intent, null, resultReceiver, null, Activity.RESULT_FIRST_USER, null, null);
	}


	@Override
	public void onError(Context context, String errorId) {
		WLAndroidUtils.warning("Received error " + errorId);
		Intent intent = new Intent(C2DM_ERROR);
		intent.putExtra(C2DM_EXTRA_ERROR_ID, errorId);
		context.sendBroadcast(intent);
	}

	private BroadcastReceiver resultReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (getResultCode() == Activity.RESULT_FIRST_USER || !WLDroidGap.isForeGround()) {
				onUnhandled(context, intent);
			}
		}
	};

	protected void onUnhandled(Context context, Intent intent) {
		String action = intent.getAction();
		if (C2DM_MESSAGE.equals(action)) {
			Message message = (Message)intent.getParcelableExtra(C2DM_EXTRA_MESSAGE);
			WLAndroidUtils.debug("Showing notification for unhandled "+ message.toString());
			intent = new Intent(C2DM_NOTIFICATION);
			intent.putExtra(C2DM_EXTRA_MESSAGE, message);
			notify(context, message.alert, message.badge, message.sound, intent);
		}
	}
	
	// ========================================== Notification Handling ====================================
	
	public static void notify(Context context, String tickerText) {
		generateNotification(context, tickerText, context.getString(RES_PUSH_NOIIFICATION_TITLE), tickerText, 0, "1", null);
	}

	public static void notify(Context context, String alert, int badge, String sound, Intent intent) {
		generateNotification(context, alert, context.getString(RES_PUSH_NOIIFICATION_TITLE), alert, badge, sound, intent);
	}

	private static void generateNotification(Context context, String ticker, String title, String msg, int badge, String sound, Intent intent) {
		int icon = RES_PUSH_NOTIFICATION_ICON;
		long when = System.currentTimeMillis();

		Notification notification = new Notification(icon, ticker, when);
		notification.setLatestEventInfo(context, title, msg, PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
		notification.number = badge;
		notification.flags |= Notification.FLAG_AUTO_CANCEL;

		NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
		notificationManager.notify(1, notification);

		if (sound != null && !("".equals(sound.trim()))) {
			playNotificationSound(context);
		}
	}

	public static void playNotificationSound(Context context) {
		Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
		if (uri != null) {
			Ringtone ringtone = RingtoneManager.getRingtone(context, uri);
			if (ringtone != null) {
				ringtone.setStreamType(AudioManager.STREAM_NOTIFICATION);
				ringtone.play();
			}
		}
	}


	/**
	 * Message - broadcast from the receiver to the Push Plugin.
	 */
	public static class Message implements Parcelable {
		private String alert;
		private String sound;
		private String payload;
		private int badge;

		public Message() {
			alert = null;
			badge = 1;
			sound = null;
			payload = null;
		}

		public JSONObject getProps() {
			JSONObject jsonObject = new JSONObject();
			try {
				jsonObject.put(C2DM_EXTRA_ALERT, alert == null ? JSONObject.NULL : alert);
				jsonObject.put(C2DM_EXTRA_BADGE, badge);
				jsonObject.put(C2DM_EXTRA_SOUND, sound == null ? JSONObject.NULL : sound);
			} catch (JSONException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
			return jsonObject;
		}
		
		public JSONObject getPayload() {
			JSONObject jsonObject = null;
			try {
				jsonObject = new JSONObject(payload);
			} catch (JSONException e) {
				jsonObject = new JSONObject();
			}
			return jsonObject;
		}
		
		@Override
		public String toString() {
			return String.format("Message(alert=%s, badge=%d, sound=%s, payload=%s)", alert, badge, sound, payload);
		}

		@Override
		public int describeContents() {
			return 0;
		}

		@Override
		public void writeToParcel(Parcel dest, int flags) {
			dest.writeString(alert);
			dest.writeInt(badge);
			dest.writeString(sound);
			dest.writeString(payload);
		}

		public static final Parcelable.Creator<Message> CREATOR = new Creator<C2DMReceiver.Message>() {
			@Override
			public Message[] newArray(int size) {
				return new Message[size];
			}

			@Override
			public Message createFromParcel(Parcel source) {
				return new Message(source);
			}
		};

		private Message(Parcel source) {
			alert = source.readString();
			badge = source.readInt();
			sound = source.readString();
			payload = source.readString();
		}
	}
}
